#include "../detail/stack_trace_windows.hh"
#include "../detail/stack_trace_linux.hh"
#include "../box/service_box.hh"
#include "../box/box_network.hh"
#include "../detail/service_logger_impl.hh"
#include "../detail/lang_impl.hh"

#include <cassert>

auto __box_assert(
  kratos::service::ServiceBox* box,
  const char* file_name,
  int file_line,
  const char* expr)->void {

  if (!box || !file_name || !expr) {
    return;
  }
  auto stack_trace = kratos::util::StackTrace::get_stack_frame_info();
  box->write_log(
    kratos::lang::LangID::LANG_ASSERTION_FAIL,
    klogger::Logger::FATAL,
    expr,
    file_name,
    file_line,
    stack_trace.c_str()
  );
}

auto __box_assert(
  kratos::service::ServiceLogger* service_logger,
  const char* file_name,
  int file_line,
  const char* expr)->void {

  using namespace kratos::service;
  using namespace kratos::lang;
  using namespace kratos::util;
  
  if (!service_logger || !file_name || !expr) {
    return;
  }

  auto stack_trace = StackTrace::get_stack_frame_info();

  auto* srv_logger_impl = dynamic_cast<ServiceLoggerImpl*>(service_logger);
  if (!srv_logger_impl) {
    return;
  }

  auto* box = srv_logger_impl->get_box();
  if (!box) {
    return;
  }

  auto* lang_impl = dynamic_cast<LangImpl*>(box->get_lang());
  if (!lang_impl) {
    return;
  }

  const auto* ctx_log = lang_impl->printf_lang(
    kratos::lang::LangID::LANG_SERVICE_ASSERTION_FAIL,
    expr,
    file_name,
    file_line,
    stack_trace.c_str()
  );

  if (ctx_log) {
    srv_logger_impl->fatal() << ctx_log;
  }
}

auto __box_assert(
  kratos::service::BoxNetwork* box_network,
  const char* file_name,
  int file_line,
  const char* expr)->void {

  using namespace kratos::service;
  using namespace kratos::lang;
  using namespace kratos::util;

  if (!box_network || !file_name || !expr) {
    return;
  }

  auto* lang_ptr = box_network->get_lang();
  auto* lang_impl = dynamic_cast<LangImpl*>(lang_ptr);
  if (!lang_impl) {
      return;
  }

  auto stack_trace = StackTrace::get_stack_frame_info();
  const auto* ctx_log = lang_impl->printf_lang(
    kratos::lang::LangID::LANG_ASSERTION_FAIL,
    expr,
    file_name,
    file_line,
    stack_trace.c_str()
  );

  if (!box_network->get_logger_appender()) {
    return;
  }

  box_network->get_logger_appender()->write(
    klogger::Logger::FATAL,
    "%s",
    ctx_log
  );
}
